package com.guqj.thread.concurrent.syntool;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CyclicBarrierTest {

	public static void main(String[] args) throws InterruptedException {
		normal();
	}

	public static void normal() {
		int n = 7;
		CyclicBarrier cyclicBarrier = new CyclicBarrier(6); // 构造参数表示参与的线程数
		for (int i = 0; i < n; i++) {
			new Thread(new Worker(cyclicBarrier)).start();
		}
	}

	public static void hasRunnable() {
		int n = 6;
		CyclicBarrier cyclicBarrier = new CyclicBarrier(6, new Runnable() { // 当所有线程都执行完成后，可以为CyclicBarrier提供额外的线程
					@Override
					public void run() {
						System.out.println("当前线程: " + Thread.currentThread().getName());
					}
				});
		for (int i = 0; i < n; i++) {
			new Thread(new Worker(cyclicBarrier)).start();
		}
	}

	public static void timeout() throws InterruptedException {
		int n = 6;
		CyclicBarrier cyclicBarrier = new CyclicBarrier(6, new Runnable() { // 当所有线程都执行完成后，可以为CyclicBarrier提供额外的线程
					@Override
					public void run() {
						System.out.println("当前线程: " + Thread.currentThread().getName());
					}
				});
		for (int i = 0; i < n; i++) {
			if (i == n - 1) {
				Thread.sleep(4000);
				new Thread(new Worker(cyclicBarrier)).start();
			} else {
				new Thread(new Worker(cyclicBarrier)).start();
			}
		}
	}

	public static void reuse() throws InterruptedException {
		int n = 6;
		CyclicBarrier cyclicBarrier = new CyclicBarrier(6, new Runnable() { // 当所有线程都执行完成后，可以为CyclicBarrier提供额外的线程
					@Override
					public void run() {
						System.out.println("当前线程: " + Thread.currentThread().getName());
					}
				});
		for (int i = 0; i < n; i++) {
			new Thread(new Worker(cyclicBarrier)).start();
		}

		Thread.sleep(5000);
		System.out.println("CyclicBarrier重用");
		
		for (int i = 0; i < n; i++) {
			new Thread(new Worker(cyclicBarrier)).start();
		}
	}
}

class Worker implements Runnable {

	private CyclicBarrier cyclicBarrier;

	public Worker(CyclicBarrier cyclicBarrier) {
		this.cyclicBarrier = cyclicBarrier;
	}

	@Override
	public void run() {
		System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
		try {
			Thread.sleep(3000);
			System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕...");
			cyclicBarrier.await(2000, TimeUnit.MILLISECONDS); // 等待时间到后，抛出异常并继续执行后面的任务
		} catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
			e.printStackTrace();
		}
		System.out.println("所有线程写入完毕，继续处理其他任务...");
	}

}